package wili.json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import wili.c.Ca;
import wili.c.Misc9a;
import wili.c.Str9a;

/**
 * @author weila 2022年9月7日
 */
public class JsonObj extends JsonNode {
	Map<String, JsonNode> attMap = new HashMap<>();// for JsonObj

	public final String guid;

	public String toString() {
		String idSt = "i" + id + ",";
		int n = lineNo2 - lineNo;
		String nlSt = "NL" + n + "=" + this.lineNo2 + "-" + this.lineNo;
		if (guid != null) {
			return idSt + "{ guid:" + guid + "}, " + nlSt;
		}
		return idSt + "{" + "}, " + nlSt;
	}

	/**
	 * 属性名集 ~>属性集
	 */
	public List<JsonNode> getAtts(boolean sort, String... atts) {
		List<JsonNode> ret = null;
		for (String att : atts) {
			JsonNode at = this.att(att);
			if (at != null) {
				if (ret == null)
					ret = new ArrayList<>(atts.length);
				ret.add(at);
			}
		}
		if (sort)
			JsonNode.sort(ret);
		return ret;
	}

	public <T extends JsonNode> T att(String att) {
		JsonNode ret = attMap.get(att);
		if (ret == null)
			return null;
		return (T) ret;
	}

	public JsonObj(JsonFile0 file, int start, JsonNode dad) {
		super(file, start, dad);
		final String fileSt = file.fileSt;
		JsonNode son;
		if (id == 18802)
			Ca.pause();
		for (int i = start + 1; i < this.endInd - 1; i++) {
			char ch = fileSt.charAt(i);
			switch (ch) {
			case ',':
				continue;
			// case '{':
			// Ca.asert(false, "");
			// son = new JsonObj(i, this);
			// i = son.end - 1;
			// continue;
			// case '[':
			// Ca.asert(false, "");
			// son = new JsonArr(i, this);
			// i = son.end - 1;
			// continue;
			case '{':
			case '[':
			case '(':
			case '}':
			case ']':
			case ')':
				Ca.asert(false, fileSt.substring(i));
			case '\"':// 对象的子必是属性
				if ("".isEmpty()) {
					String qt = Str9a.readQuote(fileSt, i);
					String attName = qt.substring(1, qt.length() - 1);
					int ind = i + qt.length();
					String st = Str9a.readPat("\\s*:\\s*", fileSt, ind);
					char ch2 = fileSt.charAt(ind = ind + st.length());
					JsonNode sonValue;
					if (ch2 == '{') {
						// 值是对象
						sonValue = new JsonObj(file, ind, this);
					} else if (ch2 == '[') {
						// 值是数组
						sonValue = new JsonArr(file, ind, this);
					} else {
						// 值是串或字面值。
						sonValue = new JsonLeaf(file, ind, this);
					}
					sonValue.setAttName(attName);
					this.attMap.put(sonValue.attName, sonValue);
					i = sonValue.endInd - 1;
				} else {
					JsonAtt__ att = new JsonAtt__(file, i, this);
					this.removeSon(att);
					son = att.valueNode;
					this.addSon(son);
					son.attName = att.name;
					this.attMap.put(son.attName, son);
					if (son.attName.contains("guid")) {
						// Ca.log(1, " JsonObj/" + son.attName + "=" + son);
					}
					i = son.endInd - 1;
				}
				continue;
			default:
				if (!Misc9a.isSpaceOrTRN(ch)) {
					Ca.asert(false, "\n" + fileSt.substring(i));
				}
			}
		}
		{
			JsonNode att = attMap.get("guid");
			if (att == null) {
				this.guid = null;
			} else {
				this.guid = att.stringValue();
				file.guidMap.put(this.guid, this);
			}
		}
	}

	@Override
	void saveToBuffer(String dent, StringBuilder buf) {
		if (id == 4)
			Ca.pause();
		if (dent.isEmpty())
			dent = "\n";
		buf.append("{");
		if (this.son("guid") != null && son("guid").stringValue.equals("9465748f-61ce-44bc-982f-31f626fd4b10"))
			Ca.pause();
		String dent2 = dent += "  ";
		for (int i = 0; i < this.sons.size(); i++) {
			JsonNode son = sons.get(i);
			String st = "\"" + son.attName + "\"";
			buf.append(dent2 + st + ": ");
			son.saveToBuffer(dent2, buf);
			if (i + 1 < sons.size()) {
				buf.append(",");
			}
		}
		buf.append(dent + "}");
	}

	public Map<String, String> getAttMap_ssMap(Function<String, String> transFun) {
		Map<String, String> ret = new HashMap<>(attMap.size());
		for (String att : this.attMap.keySet()) {
			JsonNode nod = attMap.get(att);
			if (nod instanceof JsonLeaf) {
				//att = transFun == null ? att : transFun.apply(att);
				String va = transFun == null ? nod.stringValue : transFun.apply(nod.stringValue);
				ret.put(att, va);
			}
		}
		return ret;
	}
}